package com.aizuda.encrypt.jsqlparse.visitor;

import cn.hutool.core.collection.CollUtil;
import com.aizuda.encrypt.jsqlparse.entity.JSQLCryptExpression;
import com.aizuda.encrypt.util.ParseSQLUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.AllValue;
import net.sf.jsqlparser.expression.AnalyticExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.ArrayConstructor;
import net.sf.jsqlparser.expression.ArrayExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.CastExpression;
import net.sf.jsqlparser.expression.CollateExpression;
import net.sf.jsqlparser.expression.ConnectByRootOperator;
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.ExtractExpression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.expression.IntervalExpression;
import net.sf.jsqlparser.expression.JdbcNamedParameter;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.JsonAggregateFunction;
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.expression.JsonFunction;
import net.sf.jsqlparser.expression.KeepExpression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.MySQLGroupConcat;
import net.sf.jsqlparser.expression.NextValExpression;
import net.sf.jsqlparser.expression.NotExpression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.NumericBind;
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
import net.sf.jsqlparser.expression.OracleHint;
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
import net.sf.jsqlparser.expression.OverlapsCondition;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.RowGetExpression;
import net.sf.jsqlparser.expression.SafeCastExpression;
import net.sf.jsqlparser.expression.SignedExpression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeKeyExpression;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.TimezoneExpression;
import net.sf.jsqlparser.expression.TryCastExpression;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.expression.ValueListExpression;
import net.sf.jsqlparser.expression.VariableAssignment;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.XMLSerializeExpr;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision;
import net.sf.jsqlparser.expression.operators.arithmetic.Modulo;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SubSelect;

import java.util.List;


/**
 * 子查询
 *
 * @author nn200433
 * @date 2022-03-02 06:49:28
 */
@Slf4j
public class ExpressionV extends VisitorHandle implements ExpressionVisitor {

    public ExpressionV(List<JSQLCryptExpression> list) {
        super(list);
    }

    @Override
    public void visit(Parenthesis parenthesis) {
        // 括号

        Expression expression = parenthesis.getExpression();
        expression.accept(new ExpressionV(list));
    }

    @Override
    public void visit(SubSelect subSelect) {
        // 子查询 表达式

        List<PlainSelect> plainSelectList = ParseSQLUtil.getPlainSelectList(subSelect.getSelectBody());
        if (CollUtil.isNotEmpty(plainSelectList)) {
            for (PlainSelect plain : plainSelectList) {
                FromItem fromItem = plain.getFromItem();
                if (null != fromItem) {
                    fromItem.accept(new FromItemV(list));
                }
                Expression where = plain.getWhere();
                if (null != where) {
                    where.accept(new ExpressionV(list));
                }
            }
        }
    }

    @Override
    public void visit(EqualsTo equalsTo) {
        // 等于 表达式

        Expression leftExp = equalsTo.getLeftExpression();
        // 判断 1 = 1 情况
        boolean isLongValue = leftExp instanceof LongValue;
        // 判断 左侧是 函数
        boolean isFunction     = leftExp instanceof Function;
        Column  leftExpression = null;
        if (!isLongValue && !isFunction) {
            leftExpression = (Column) leftExp;
        }
        handler(leftExpression, equalsTo.getRightExpression(), equalsTo.toString());
    }

    @Override
    public void visit(NotEqualsTo notEqualsTo) {
        // 不等于 表达式

        log.debug("---> [Mybatis SQL 解析拦截] notEqualsTo");
    }

    @Override
    public void visit(GreaterThan greaterThan) {
        // 大于 表达式

        log.debug("---> [Mybatis SQL 解析拦截] greaterThan");
    }

    @Override
    public void visit(GreaterThanEquals greaterThanEquals) {
        // 大于等于 表达式

        log.debug("---> [Mybatis SQL 解析拦截] greaterThanEquals");
    }

    @Override
    public void visit(MinorThan minorThan) {
        // 小于 表达式

        log.debug("---> [Mybatis SQL 解析拦截] minorThan");
    }

    @Override
    public void visit(MinorThanEquals minorThanEquals) {
        // 小于等于 表达式

        log.debug("---> [Mybatis SQL 解析拦截] minorThanEquals");
    }

    @Override
    public void visit(LikeExpression likeExpression) {
        // like 表达式

        Expression leftExp        = likeExpression.getLeftExpression();
        Column     leftExpression = (Column) leftExp;
        handler(leftExpression, likeExpression.getRightExpression(), likeExpression.toString());
    }

    @Override
    public void visit(AndExpression andExpression) {
        // and 表达式

        Expression leftExpression = andExpression.getLeftExpression();
        if (null != leftExpression) {
            leftExpression.accept(new ExpressionV(list));
        }
        Expression rightExpression = andExpression.getRightExpression();
        if (null != rightExpression) {
            rightExpression.accept(new ExpressionV(list));
        }
    }

    @Override
    public void visit(OrExpression orExpression) {
        // or 表达式
        Expression leftExpression = orExpression.getLeftExpression();
        if (null != leftExpression) {
            leftExpression.accept(new ExpressionV(list));
        }
        Expression rightExpression = orExpression.getRightExpression();
        if (null != rightExpression) {
            rightExpression.accept(new ExpressionV(list));
        }
    }

    @Override
    public void visit(XorExpression orExpression) {
        // 异或 表达式

        Expression leftExpression = orExpression.getLeftExpression();
        if (null != leftExpression) {
            leftExpression.accept(new ExpressionV(list));
        }
        Expression rightExpression = orExpression.getRightExpression();
        if (null != rightExpression) {
            rightExpression.accept(new ExpressionV(list));
        }
    }

    @Override
    public void visit(InExpression inExpression) {
        // in 表达式

        Expression leftExpression = inExpression.getLeftExpression();
        if (leftExpression != null) {
            leftExpression.accept(new ExpressionV(list));
        }
        Expression rightExpression = inExpression.getRightExpression();
        if (rightExpression != null) {
            rightExpression.accept(new ExpressionV(list));
        }
        ItemsList rightItemsList = inExpression.getRightItemsList();
        if (rightItemsList != null) {
            Column leftExp = (Column) leftExpression;
            rightItemsList.accept(new ItemsListV(list, leftExp, inExpression.toString()));
        }

        log.debug("---> [Mybatis SQL 解析拦截] inExpression");
    }

    @Override
    public void visit(IsNullExpression isNullExpression) {
        // is null 表达式

        log.debug("---> [Mybatis SQL 解析拦截] isNullExpression");
    }

    // =========================================== 其他用到了再管 ===========================================

    @Override
    public void visit(BitwiseRightShift aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] BitwiseRightShift");
    }

    @Override
    public void visit(BitwiseLeftShift aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] BitwiseLeftShift");
    }

    @Override
    public void visit(NullValue nullValue) {
        log.debug("---> [Mybatis SQL 解析拦截] NullValue");
    }

    @Override
    public void visit(Function function) {
        log.debug("---> [Mybatis SQL 解析拦截] Function");
    }

    @Override
    public void visit(SignedExpression signedExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] SignedExpression");
    }

    @Override
    public void visit(JdbcParameter jdbcParameter) {
        log.debug("---> [Mybatis SQL 解析拦截] JdbcParameter");
    }

    @Override
    public void visit(JdbcNamedParameter jdbcNamedParameter) {
        log.debug("---> [Mybatis SQL 解析拦截] JdbcNamedParameter");
    }

    @Override
    public void visit(DoubleValue doubleValue) {
        log.debug("---> [Mybatis SQL 解析拦截] DoubleValue");
    }

    @Override
    public void visit(LongValue longValue) {
        log.debug("---> [Mybatis SQL 解析拦截] LongValue");
    }

    @Override
    public void visit(HexValue hexValue) {
        log.debug("---> [Mybatis SQL 解析拦截] HexValue");
    }

    @Override
    public void visit(DateValue dateValue) {
        log.debug("---> [Mybatis SQL 解析拦截] DateValue");
    }

    @Override
    public void visit(TimeValue timeValue) {
        log.debug("---> [Mybatis SQL 解析拦截] TimeValue");
    }

    @Override
    public void visit(TimestampValue timestampValue) {
        log.debug("---> [Mybatis SQL 解析拦截] TimestampValue");
    }

    @Override
    public void visit(StringValue stringValue) {
        log.debug("---> [Mybatis SQL 解析拦截] StringValue");
    }

    @Override
    public void visit(Addition addition) {
        log.debug("---> [Mybatis SQL 解析拦截] Addition");
    }

    @Override
    public void visit(Division division) {
        log.debug("---> [Mybatis SQL 解析拦截] Division");
    }

    @Override
    public void visit(IntegerDivision division) {
        log.debug("---> [Mybatis SQL 解析拦截] IntegerDivision");
    }

    @Override
    public void visit(Multiplication multiplication) {
        log.debug("---> [Mybatis SQL 解析拦截] Multiplication");
    }

    @Override
    public void visit(Subtraction subtraction) {
        log.debug("---> [Mybatis SQL 解析拦截] Subtraction");
    }

    @Override
    public void visit(Between between) {
        log.debug("---> [Mybatis SQL 解析拦截] Between");
    }

    @Override
    public void visit(OverlapsCondition overlapsCondition) {
        log.debug("---> [Mybatis SQL 解析拦截] overlapsCondition");
    }

    @Override
    public void visit(FullTextSearch fullTextSearch) {
        log.debug("---> [Mybatis SQL 解析拦截] FullTextSearch");
    }

    @Override
    public void visit(IsBooleanExpression isBooleanExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] IsBooleanExpression");
    }

    @Override
    public void visit(Column tableColumn) {
        log.debug("---> [Mybatis SQL 解析拦截] Column");
    }

    @Override
    public void visit(CaseExpression caseExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] CaseExpression");
    }

    @Override
    public void visit(WhenClause whenClause) {
        log.debug("---> [Mybatis SQL 解析拦截] WhenClause");
    }

    @Override
    public void visit(ExistsExpression existsExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] ExistsExpression");
    }

    @Override
    public void visit(AnyComparisonExpression anyComparisonExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] AnyComparisonExpression");
    }

    @Override
    public void visit(Concat concat) {
        log.debug("---> [Mybatis SQL 解析拦截] Concat");
    }

    @Override
    public void visit(Matches matches) {
        log.debug("---> [Mybatis SQL 解析拦截] Matches");
    }

    @Override
    public void visit(BitwiseAnd bitwiseAnd) {
        log.debug("---> [Mybatis SQL 解析拦截] BitwiseAnd");
    }

    @Override
    public void visit(BitwiseOr bitwiseOr) {
        log.debug("---> [Mybatis SQL 解析拦截] BitwiseOr");
    }

    @Override
    public void visit(BitwiseXor bitwiseXor) {
        log.debug("---> [Mybatis SQL 解析拦截] BitwiseXor");
    }

    @Override
    public void visit(CastExpression cast) {
        log.debug("---> [Mybatis SQL 解析拦截] CastExpression");
    }

    @Override
    public void visit(TryCastExpression cast) {
        log.debug("---> [Mybatis SQL 解析拦截] TryCastExpression");
    }

    @Override
    public void visit(SafeCastExpression cast) {
        log.debug("---> [Mybatis SQL 解析拦截] cast");
    }

    @Override
    public void visit(Modulo modulo) {
        log.debug("---> [Mybatis SQL 解析拦截] Modulo");
    }

    @Override
    public void visit(AnalyticExpression aexpr) {
        log.debug("---> [Mybatis SQL 解析拦截] AnalyticExpression");
    }

    @Override
    public void visit(ExtractExpression eexpr) {
        log.debug("---> [Mybatis SQL 解析拦截] ExtractExpression");
    }

    @Override
    public void visit(IntervalExpression iexpr) {
        log.debug("---> [Mybatis SQL 解析拦截] IntervalExpression");
    }

    @Override
    public void visit(OracleHierarchicalExpression oexpr) {
        log.debug("---> [Mybatis SQL 解析拦截] OracleHierarchicalExpression");
    }

    @Override
    public void visit(RegExpMatchOperator rexpr) {
        log.debug("---> [Mybatis SQL 解析拦截] RegExpMatchOperator");
    }

    @Override
    public void visit(JsonExpression jsonExpr) {
        log.debug("---> [Mybatis SQL 解析拦截] JsonExpression");
    }

    @Override
    public void visit(JsonOperator jsonExpr) {
        log.debug("---> [Mybatis SQL 解析拦截] JsonOperator");
    }

    @Override
    public void visit(RegExpMySQLOperator regExpMySQLOperator) {
        log.debug("---> [Mybatis SQL 解析拦截] RegExpMySQLOperator");
    }

    @Override
    public void visit(UserVariable var) {
        log.debug("---> [Mybatis SQL 解析拦截] UserVariable");
    }

    @Override
    public void visit(NumericBind bind) {
        log.debug("---> [Mybatis SQL 解析拦截] NumericBind");
    }

    @Override
    public void visit(KeepExpression aexpr) {
        log.debug("---> [Mybatis SQL 解析拦截] KeepExpression");
    }

    @Override
    public void visit(MySQLGroupConcat groupConcat) {
        log.debug("---> [Mybatis SQL 解析拦截] MySQLGroupConcat");
    }

    @Override
    public void visit(ValueListExpression valueList) {
        log.debug("---> [Mybatis SQL 解析拦截] ValueListExpression");
    }

    @Override
    public void visit(RowConstructor rowConstructor) {
        log.debug("---> [Mybatis SQL 解析拦截] RowConstructor");
    }

    @Override
    public void visit(RowGetExpression rowGetExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] RowGetExpression");
    }

    @Override
    public void visit(OracleHint hint) {
        log.debug("---> [Mybatis SQL 解析拦截] OracleHint");
    }

    @Override
    public void visit(TimeKeyExpression timeKeyExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] TimeKeyExpression");
    }

    @Override
    public void visit(DateTimeLiteralExpression literal) {
        log.debug("---> [Mybatis SQL 解析拦截] DateTimeLiteralExpression");
    }

    @Override
    public void visit(NotExpression aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] NotExpression");
    }

    @Override
    public void visit(NextValExpression aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] NextValExpression");
    }

    @Override
    public void visit(CollateExpression aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] CollateExpression");
    }

    @Override
    public void visit(SimilarToExpression aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] SimilarToExpression");
    }

    @Override
    public void visit(ArrayExpression aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] ArrayExpression");
    }

    @Override
    public void visit(ArrayConstructor aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] ArrayConstructor");
    }

    @Override
    public void visit(VariableAssignment aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] VariableAssignment");
    }

    @Override
    public void visit(XMLSerializeExpr aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] XMLSerializeExpr");
    }

    @Override
    public void visit(TimezoneExpression aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] TimezoneExpression");
    }

    @Override
    public void visit(JsonAggregateFunction aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] JsonAggregateFunction");
    }

    @Override
    public void visit(JsonFunction aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] JsonFunction");
    }

    @Override
    public void visit(ConnectByRootOperator aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] ConnectByRootOperator");
    }

    @Override
    public void visit(OracleNamedFunctionParameter aThis) {
        log.debug("---> [Mybatis SQL 解析拦截] OracleNamedFunctionParameter");
    }

    @Override
    public void visit(AllColumns allColumns) {
        log.debug("---> [Mybatis SQL 解析拦截] AllColumns");
    }

    @Override
    public void visit(AllTableColumns allTableColumns) {
        log.debug("---> [Mybatis SQL 解析拦截] AllTableColumns");
    }

    @Override
    public void visit(AllValue allValue) {
        log.debug("---> [Mybatis SQL 解析拦截] AllValue");
    }

    @Override
    public void visit(IsDistinctExpression isDistinctExpression) {
        log.debug("---> [Mybatis SQL 解析拦截] IsDistinctExpression");
    }

    @Override
    public void visit(GeometryDistance geometryDistance) {
        log.debug("---> [Mybatis SQL 解析拦截] IsDistinctExpression");
    }

}